package org.example.cgg.tools.excel;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.util.List;

public class ExcelTool {

    public static Workbook createXLS() {
        Workbook workbook = new HSSFWorkbook();
        return workbook;
    }

    public static Workbook createXLSX() {
        Workbook workbook = new XSSFWorkbook();
        return workbook;
    }

    private static CellStyle getHeaderStyle(Workbook workbook) {
        CellStyle headerCellStyle = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true);
        headerCellStyle.setFont(font);
        headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
        headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        headerCellStyle.setBorderTop(BorderStyle.THIN);
        headerCellStyle.setBorderBottom(BorderStyle.THIN);
        headerCellStyle.setBorderLeft(BorderStyle.THIN);
        headerCellStyle.setBorderRight(BorderStyle.THIN);
        return headerCellStyle;
    }

    public static int createHeader(List<Header> headers, Workbook workbook, Sheet sheet) {
        CellStyle headerCellStyle = getHeaderStyle(workbook);
        int headerRowNum = getHeaderRowNum(headers, 1);
        int headerColumnNum = 0;
        for (Header header : headers) {
            headerColumnNum += ExcelTool.getHeaderColumnNum(header);
        }
        System.out.println("[Header Row Num]=" + headerRowNum + "    [Header Column Num]=" + headerColumnNum);
        for (int i = 0; i < headerRowNum; i++) {
            Row row = sheet.createRow(i);
            for (int j = 0; j < headerColumnNum; j++) {
                Cell cell = row.createCell(j);
                cell.setCellStyle(headerCellStyle);
            }
        }
        doCreateHeader(headers, sheet, headerRowNum, 0, 0);
        return headerRowNum;
    }

    private static void doCreateHeader(List<Header> headers, Sheet sheet, int headerRowNum, int rowIndex, int columnIndex) {
        Row row = sheet.getRow(rowIndex);
        for (Header header : headers) {
            if (header.getChildren() != null && header.getChildren().size() > 0) {
                int headerColumnNum = getHeaderColumnNum(header);
                if (headerColumnNum > 1) {
                    CellRangeAddress cellRangeAddress = new CellRangeAddress(rowIndex, rowIndex, columnIndex, columnIndex + headerColumnNum - 1);
                    sheet.addMergedRegion(cellRangeAddress);
                }
                Cell cell = row.getCell(columnIndex);
                cell.setCellValue(header.getDisplayName());
                doCreateHeader(header.getChildren(), sheet, headerRowNum, rowIndex + 1, columnIndex);
                columnIndex += headerColumnNum;
            } else {
                if (rowIndex < headerRowNum - 1) {
                    CellRangeAddress cellRangeAddress = new CellRangeAddress(rowIndex, headerRowNum - 1, columnIndex, columnIndex);
                    sheet.addMergedRegion(cellRangeAddress);
                }
                Cell cell = row.getCell(columnIndex);
                cell.setCellValue(header.getDisplayName());
                sheet.setColumnWidth(columnIndex, header.getWidth() * 256);
                columnIndex++;
            }
        }
    }

    private static int getHeaderRowNum(List<Header> headers, int level) {
        int totalRow = level;
        for (Header header : headers) {
            if (header.getChildren() != null && header.getChildren().size() > 0) {
                int currentRow = getHeaderRowNum(header.getChildren(), level + 1);
                if (currentRow > totalRow) {
                    totalRow = currentRow;
                }
            }
        }
        return totalRow;
    }

    private static int getHeaderColumnNum(Header header) {
        int totalColumn = 0;
        if (header.getChildren() == null || header.getChildren().size() == 0) {
            totalColumn++;
        } else {
            for (Header child : header.getChildren()) {
                totalColumn += getHeaderColumnNum(child);
            }
        }
        return totalColumn;
    }
}
